/*******************************************************************************
* Copyright (c) 2010, 2018 西安秦晔信息科技有限公司
* Licensed under the Apache License, Version 2.0 (the "License");
*    you may not use this file except in compliance with the License.
*    You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*    Unless required by applicable law or agreed to in writing, software
*    distributed under the License is distributed on an "AS IS" BASIS,
*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*    See the License for the specific language governing permissions and
*    limitations under the License.
*******************************************************************************/
package com.qinyeit.serviceapp.service.stores.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qinyeit.serviceapp.entity.*;
import com.qinyeit.serviceapp.entity.enums.*;
import com.qinyeit.serviceapp.exception.BusinessRunTimeException;
import com.qinyeit.serviceapp.repository.stores.StoreInOrderDetailRepository;
import com.qinyeit.serviceapp.repository.stores.TransferOrderDetailRepository;
import com.qinyeit.serviceapp.service.materials.MaterialService;
import com.qinyeit.serviceapp.service.stores.*;
import com.qinyeit.serviceapp.utils.CompuUtils;
import com.qinyeit.serviceapp.utils.LocalUtils;
import com.qinyetech.springstage.core.date.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.qinyetech.springstage.core.service.BaseService;
import com.qinyeit.serviceapp.repository.stores.TransferOrderRepository;

import java.util.*;

/** 
 * ClassName: TransferOrderServiceImpl <br/> 
 * Function: 调拨单据 业务实现 <br/> 
 * date: 2018-11-08 14:02:44 <br/> 
 * 
 * @author liuwenjin
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@Transactional
public class TransferOrderServiceImpl extends BaseService<TransferOrder, Long> implements TransferOrderService {


	@Autowired
	private TransferOrderRepository transferOrderRepository;
	@Autowired
	private TransferOrderDetailRepository transferOrderDetailRepository;
	@Autowired
	private StoreInOrderService storeInOrderService;
	@Autowired
	private StoreOutOrderService storeOutOrderService;
	@Autowired
	private StoreOutOrderDetailService storeOutOrderDetailService;
	@Autowired
	private StockService stockService;
	@Autowired
	private StoreInOrderDetailService storeInOrderDetailService;
	@Autowired
	private MaterialService materialService;


	@Override
	public void saveData(JSONObject data, Long merchantGroupId) {
		if(data==null){
			throw new BusinessRunTimeException("订单信息为空",10001);
		}
		JSONObject orderData = data.getJSONObject("transferOrders");
		if(orderData==null){
			throw new BusinessRunTimeException("订单信息为空",10002);
		}

		if(orderData.getLong("transferOutId")==null){
			throw new BusinessRunTimeException("请选择调出仓库",10004);
		}
		if(orderData.getLong("transferInId")==null){
			throw new BusinessRunTimeException("请选择调入仓库",10005);
		}
		if(orderData.getString("transferOutId").equals(orderData.getString("transferInId"))){
			throw new BusinessRunTimeException("调出仓库和调入仓库不能一样",10006);
		}
		JSONArray detailData = data.getJSONArray("details");
		if(CollectionUtils.isEmpty(detailData)){
			throw new BusinessRunTimeException("订单明细为空",10003);
		}
		TransferOrder transferOrder = null;
		Long id = orderData.getLong("id");
		if(id==null){
			//保存
			transferOrder = new TransferOrder();
			transferOrder.setNo(LocalUtils.getOrderNo());
		}else {
			//编辑
			transferOrder = this.findById(id);
			//删除明细
			transferOrderRepository.deleteOrderDetails(id,merchantGroupId);
		}
		double amountSum = 0.0;
		transferOrder.setOperator(null);
		transferOrder.setOperatorName("");
		transferOrder.setOperateTime(new Date());
		int type = data.getInteger("type");
		if(type==1){
			//保存
			transferOrder.setState(TransferState.NOAUDIT);
		}else if(type==2){
			//提交并审核
			transferOrder.setState(TransferState.AUDIT);
		}
		transferOrder.setTransferInId(orderData.getLong("transferInId"));
		transferOrder.setTransferInName(orderData.getString("transferInName"));
		transferOrder.setTransferOutId(orderData.getLong("transferOutId"));
		transferOrder.setTransferOutName(orderData.getString("transferOutName"));
		transferOrder.setMerchantGroupId(merchantGroupId);

		JSONObject item ;
		TransferOrderDetail detail = null;
		List<TransferOrderDetail> detailList = Lists.newArrayList();
		Material material = null;
		for (int i = 0; i < detailData.size(); i++) {
			item = detailData.getJSONObject(i);
			detail = new TransferOrderDetail();
			material = materialService.findById(item.getLong("materialId"));
			detail.setOrder(transferOrder);
			detail.setCount(item.getDouble("count"));
			detail.setPrice(item.getDouble("price"));
			detail.setAmount(CompuUtils.multiply(item.getDouble("count"),item.getDouble("price")));
			detail.setMaterialId(item.getLong("materialId"));
			detail.setName(item.getString("name"));
			detail.setNo(item.getString("no"));
			detail.setSpec(item.getString("spec"));
			detail.setUnit(item.getString("unit"));
			detail.setMerchantGroupId(merchantGroupId);
			detail.setCreateAt(DateUtils.date());
			detail.setCode(material.getCode());
			amountSum = CompuUtils.add(amountSum,detail.getAmount());
			detailList.add(detail);
		}
		transferOrderDetailRepository.saveAll(detailList);
		transferOrder.setAmount(amountSum);
		transferOrder = this.update(transferOrder);

		if(transferOrder.getState()==TransferState.AUDIT){
			//已审核
			//将调拨单中的数据保存到出库单和入库单 修改库存
			this.apply(transferOrder,detailList);
		}
	}

	//将调拨单中的数据保存到出库单和入库单 进出库存记录中
	private void apply(TransferOrder order, List<TransferOrderDetail> details){
		//合并detail中重复的商品
		Map<Long, TransferOrderDetail> materialMap = Maps.newHashMap();

		for(TransferOrderDetail detail : details){
			if(materialMap.containsKey(detail.getMaterialId())){
				TransferOrderDetail tempDetail = materialMap.get(detail.getMaterialId());
				tempDetail.setCount(CompuUtils.add(tempDetail.getCount(),detail.getCount()));
				tempDetail.setAmount(tempDetail.getCount()*tempDetail.getPrice());
				materialMap.put(detail.getMaterialId(), tempDetail);
			}else{
				materialMap.put(detail.getMaterialId(), detail);
			}
		}
		List<TransferOrderDetail> transferDetails = Lists.newArrayList(materialMap.values());

		//保存出库单据
		StockInOut stockInOut;
		StoreOutOrder outOrder = new StoreOutOrder();
		outOrder.setMerchantGroupId(order.getMerchantGroupId());
		outOrder.setNo(LocalUtils.getOrderNo());
		outOrder.setOutTime(DateUtils.date());
		outOrder.setState(StoreOutState.AUDIT);
		outOrder.setType(StoreOutType.DIAOBOBOUT);
		outOrder.setWarehouseId(order.getTransferOutId());
		outOrder.setWarehouseName(order.getTransferOutName());
		outOrder.setAmount(order.getAmount());
		outOrder.setChecker(order.getOperator());
		outOrder.setCheckerName(order.getOperatorName());
		outOrder.setOperator(order.getOperator());
		outOrder.setOperatorName(order.getOperatorName());
		storeOutOrderService.save(outOrder);
		StoreOutOrderDetail outDetail;
		for(TransferOrderDetail detail : transferDetails){
			//保存出库记录明细
			outDetail = new StoreOutOrderDetail();
			outDetail.setMerchantGroupId(order.getMerchantGroupId());
			outDetail.setNo(detail.getNo());
			outDetail.setSpec(detail.getSpec());
			outDetail.setName(detail.getName());
			outDetail.setMaterialId(detail.getMaterialId());
			outDetail.setUnit(detail.getUnit());
			outDetail.setOrder(outOrder);
			outDetail.setCount(detail.getCount());
			outDetail.setPrice(detail.getPrice());
			outDetail.setTotal(detail.getAmount());
			outDetail.setCode(detail.getCode());
			storeOutOrderDetailService.save(outDetail);

			//修改库存 不计算成本均价
			Stock stock = stockService.getStocks(outOrder.getWarehouseId(),detail.getMaterialId(),outOrder.getMerchantGroupId());
			if(stock==null){
				throw new BusinessRunTimeException("改商品暂无库存",10001);
			}
			stock.setCount(CompuUtils.subtract(stock.getCount(),outDetail.getCount()));
			stock.setAmount(CompuUtils.multiply(stock.getCount(),stock.getCost()));
			stockService.update(stock);
		}

		StoreInOrder inOrder = new StoreInOrder();
		inOrder.setMerchantGroupId(order.getMerchantGroupId());
		inOrder.setNo(LocalUtils.getOrderNo());
		inOrder.setInTime(DateUtils.date());
		inOrder.setType(StoreInType.DIAOBOBIN);
		inOrder.setAmount(order.getAmount());
		inOrder.setState(StoreInState.AUDIT);
		inOrder.setWarehouseId(order.getTransferInId());
		inOrder.setWarehouseName(order.getTransferInName());
		storeInOrderService.save(inOrder);
		StoreInOrderDetail inDetail;

		for(TransferOrderDetail detail : transferDetails){
			//保存出库记录明细
			inDetail = new StoreInOrderDetail();
			inDetail.setMerchantGroupId(order.getMerchantGroupId());
			inDetail.setMaterialId(detail.getMaterialId());
			inDetail.setNo(detail.getNo());
			inDetail.setSpec(detail.getSpec());
			inDetail.setName(detail.getName());
			inDetail.setOrder(inOrder);
			inDetail.setUnit(detail.getUnit());
			inDetail.setStorageUnit(detail.getUnit());
			inDetail.setStorageCount(detail.getCount());
			inDetail.setStoragePrice(detail.getPrice());
			inDetail.setStorageTotal(detail.getAmount());
			inDetail.setCode(detail.getCode());
			storeInOrderDetailService.save(inDetail);

			//修改库存 并计算成本均价
			Stock stock = stockService.getStocks(inOrder.getWarehouseId(),detail.getMaterialId(),outOrder.getMerchantGroupId());
			if(stock==null){
				//没有库存 直接添加
				stock = new Stock();
				stock.setMerchantGroupId(order.getMerchantGroupId());
				stock.setMaterialId(detail.getMaterialId());
				stock.setWarehouseId(order.getTransferInId());
				stock.setCount(inDetail.getStorageCount());
				stock.setCost(inDetail.getStoragePrice());
				stock.setAmount(CompuUtils.multiply(stock.getCount(),stock.getCost()));
			}else {
				stock.setCount(CompuUtils.add(stock.getCount(),inDetail.getStorageCount()));
				//计算成本均价
				stock.setCost((CompuUtils.add(stock.getCount()*stock.getCost(),inDetail.getStorageCount()*inDetail.getStoragePrice()))/(CompuUtils.add(stock.getCount(),inDetail.getStorageCount())));
				stock.setAmount(CompuUtils.multiply(stock.getCount(),stock.getCost()));
			}
			stockService.update(stock);
			log.info("调拨入库");
		}
	}


}